package com.bodystm.server;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import com.bodystm.web.TemperatureDevice;

/**
 * 根据曲线拟合算法预估达到平衡时的温度
 * @author a
 *
 */
public class Estimate {
	/**
	 * 
	 * @param dataIn5Min
	 * @param date4DataIn5Min
	 * @return
	 */
	public static float getStableValue(List<Float> dataIn5Min,List<Date> date4DataIn5Min){
		try {
			float A=1;//系数A
			float B=0.0001f;//系数B
			float C=dataIn5Min.get(0);//第一个大于35的值
			double error=0;//误差
			double totalError=0;//总误差：每个值的误差的平方和
			double minTotalError=0;//最小的总误差
			float A4MinError=1;
			float B4MinError=0.0001f;
			long t=0;//每个点对应的时间，单位为秒
			long tFirst=date4DataIn5Min.get(0).getTime();
			for(A=1;A<=5;A+=0.04){
				for(B=0.0001f;B<=0.01;B+=0.0001){
					totalError=0;
					for(int i=0;i<dataIn5Min.size();i++){
						if(i==0){
							t=0;
						}else{
							t=(date4DataIn5Min.get(i).getTime()-tFirst)/1000;
						}
						error=A*(1-Math.exp(-B*t))+C-dataIn5Min.get(i);
						totalError+=error*error;
					}
					if(A==1&&B==0.0001f){
						minTotalError=totalError;
						A4MinError=1;
						B4MinError=0.0001f;
					}else if(totalError<minTotalError){
						minTotalError=totalError;
						A4MinError=A;
						B4MinError=B;
					}
				}
			}
			//此时A4MinError为A最佳取值
			float Result=A4MinError+C;
			return Result;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return 0;
		}
	}
	public static List<Float> getListK(List<Float> dataIn5Min,Integer indexOf33,Integer indexOf35){
		for(int i=0;i<dataIn5Min.size();i++){
			if(dataIn5Min.get(i)>35){
				if(indexOf35==-1) indexOf35=i;
			}else if(dataIn5Min.get(i)>33){
				if(indexOf33==-1) indexOf33=i;
			}
			dataIn5Min.set(i, dataIn5Min.get(i)+C2K);		
		}
		return dataIn5Min;
			
	}
	private static final float C2K =273.15f;
	public static float getStableValue2(TemperatureDevice temperatureDevice){//List<Float> dataIn5MinOri,List<Date> date4DataIn5MinOri,
		try {
			List<Float> dataIn5Min=new ArrayList<Float>();
			dataIn5Min.addAll(temperatureDevice.getDataIn20Min());
			List<Date> date4DataIn5Min=new ArrayList<Date>();
			date4DataIn5Min.addAll(temperatureDevice.getDate4DataIn20Min());
			Integer indexOf33=0;
			Integer indexOf35=-1;
			for(int i=0;i<dataIn5Min.size();i++){
				if(dataIn5Min.get(i)>35){
					if(indexOf35==-1) indexOf35=i;
				}
//				else if(dataIn5Min.get(i)>33){
//					if(indexOf33==-1) indexOf33=i;
//				}
				dataIn5Min.set(i, dataIn5Min.get(i)+C2K);		
			}
			//dataIn5Min=getListK(dataIn5Min,indexOf33,indexOf35);
			if(dataIn5Min.size()<3)return 0;
			float timefacter=0;
			long tFirst=temperatureDevice.getFirstDataTime().getTime();//date4DataIn5Min.get(0).getTime();//贴片第一次上数的时间
			long TOf33=0;//第一次温度高于33度的时间，单位为毫秒
			long TOf35;
			//获取系数C --->timefacter
//			if(indexOf33==-1){//如果第一个数据就大于33摄氏度
//				TOf33=tFirst;
//				return 33;
//			}else{
//				TOf33=date4DataIn5Min.get(indexOf33).getTime();
//			}
			TOf33=date4DataIn5Min.get(0).getTime();
			if(indexOf35==-1){//如果自始至终没有高于35度的数据
				timefacter=0;
			}else{
				TOf35=date4DataIn5Min.get(indexOf35).getTime();
				if((TOf35-TOf33)/1000>220){
					timefacter=0;
				}else{
					int timeOfReach33=(int) ((TOf33-tFirst)/1000);
					if(timeOfReach33<30){
						timefacter=0.32f*(70+timeOfReach33);
					}else if(timeOfReach33<100){
						timefacter=0.32f*timeOfReach33;
					}else if(timeOfReach33<180){
						timefacter=0.32f*(timeOfReach33-70);
					}else{
						timefacter=20.8f;
					}
				}
			}/*
			if((date4DataIn5Min.get(date4DataIn5Min.size()-1).getTime()-date4DataIn5Min.get(indexOf33).getTime())/1000<=300){
				
				temperatureDevice.setTimefacter(timefacter);
			}else{
				timefacter=temperatureDevice.getTimefacter();
				System.out.println("五分钟后timefacter:"+timefacter);
			}*/
			//
			float T0=dataIn5Min.get(indexOf33);//第一个大于33摄氏度的温度
			float A=1;//系数A
			float B=0.0001f;//系数B
			float C=dataIn5Min.get(0);//第一个大于35的值
			double error=0;//误差
			double totalError=0;//总误差：每个值的误差的平方和
			double minTotalError=0;//最小的总误差
			float A4MinError=1;
			float B4MinError=0.0001f;
			long t=0;//每个点对应的时间，单位为秒
			for(A=1;A<=5;A+=0.04){
				for(B=0.001f;B<=0.01;B+=0.0001){
					totalError=0;
					for(int i=indexOf33;i<dataIn5Min.size();i++){
						t=(date4DataIn5Min.get(i).getTime()-TOf33)/1000;
						error=A*(1-Math.exp(-B*(t+timefacter)))+T0-dataIn5Min.get(i);
						totalError+=error*error;
					}
					if(A==1&&B==0.001f){
						minTotalError=totalError;
						A4MinError=1;
						B4MinError=0.001f;
					}else if(totalError<minTotalError){
						minTotalError=totalError;
						A4MinError=A;
						B4MinError=B;
					}
				}
			}
			//此时A4MinError为A最佳取值
			//float Result=A4MinError+T0;
			//return Result-C2K;
//			float Result= (float) (A4MinError*(1-Math.exp(-B4MinError*(900-(TOf33-tFirst)/1000+timefacter)))+T0-C2K);
			float Result= (float) (A4MinError*(1-Math.exp(-B4MinError*(900+timefacter)))+T0-C2K);
			if((date4DataIn5Min.get(date4DataIn5Min.size()-1).getTime()-TOf33)/1000<=300){
				if(temperatureDevice.getData0()==0){
					temperatureDevice.setData0(Result);
					temperatureDevice.setIfFirstTFis0(timefacter==0);
				}else{
					//Result-=1.4-(1.4/120)*((date4DataIn5Min.get(date4DataIn5Min.size()-1).getTime()-TOf33)/1000-180);
					if(temperatureDevice.isIfFirstTFis0()){
						Result=(Result+temperatureDevice.getData0())/2;
					}else{
						float adj=(float) (1.5-(temperatureDevice.getData0()-Result));
						Result-=adj;
					}
					
				}
			}
			return Result;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return 0;
		}
	}
	public static float getStableValue4(TemperatureDevice temperatureDevice){//List<Float> dataIn5MinOri,List<Date> date4DataIn5MinOri,
		try {
			List<Float> dataIn5Min=new ArrayList<Float>();
			dataIn5Min.addAll(temperatureDevice.getDataIn20Min());
			List<Date> date4DataIn5Min=new ArrayList<Date>();
			date4DataIn5Min.addAll(temperatureDevice.getDate4DataIn20Min());
			Integer indexOf33=0;
			Integer indexOf35=-1;
			for(int i=0;i<dataIn5Min.size();i++){
				if(dataIn5Min.get(i)>35){
					if(indexOf35==-1) indexOf35=i;
				}

				dataIn5Min.set(i, dataIn5Min.get(i)+C2K);		
			}
			//dataIn5Min=getListK(dataIn5Min,indexOf33,indexOf35);
			if(dataIn5Min.size()<3)return 0;
			float timefacter=0;
			long tFirst=temperatureDevice.getFirstDataTime().getTime();//date4DataIn5Min.get(0).getTime();//贴片第一次上数的时间
			long TOf33=0;//第一次温度高于33度的时间，单位为毫秒
			long TOf35;
			//获取系数C --->timefacter
			TOf33=date4DataIn5Min.get(0).getTime();
			if(indexOf35==-1){//如果自始至终没有高于35度的数据
				timefacter=0;
			}else{
				TOf35=date4DataIn5Min.get(indexOf35).getTime();
				if((TOf35-TOf33)/1000>220){
					timefacter=0;
				}else{
					int timeOfReach33=(int) ((TOf33-tFirst)/1000);
					if(timeOfReach33<30){
						timefacter=0.34f*(70+timeOfReach33);
					}else if(timeOfReach33<100){
						timefacter=0.34f*timeOfReach33;
					}else if(timeOfReach33<180){
						timefacter=0.34f*(timeOfReach33-70);
					}else{
						timefacter=22.1f;//0.34*65
					}
				}
			}
			timefacter-=25;
			//数据划分比例然后采用权重
			int indexOfArea4=(int) (Math.round(dataIn5Min.size()*0.4)-1);
			float W4Area4=0,W4Area6=0,adj=0.09f;//权重以及权重系数
			int secondsAfterReach33=(int) ((date4DataIn5Min.get(date4DataIn5Min.size()-1).getTime()-TOf33)/1000);
			if(temperatureDevice.getResult4Latest3Times().size()==0){//secondsAfterReach33==180){
				W4Area4=0.85f;
				W4Area6=1.65f;
			}else if(secondsAfterReach33<300){
				W4Area4=0.95f+0.1f*adj;
				W4Area6=1.8f-adj;
				
			}else{
				W4Area4=1;
				W4Area6=1;
			}
			//
			float T0=dataIn5Min.get(indexOf33);//第一个大于33摄氏度的温度
			float A=1;//系数A
			float B=0.0001f;//系数B
			float C=dataIn5Min.get(0);//第一个大于35的值
			double error=0;//误差
			double totalError=0;//总误差：每个值的误差的平方和
			double minTotalError=0;//最小的总误差
			float A4MinError=1;
			float B4MinError=0.0001f;
			long t=0;//每个点对应的时间，单位为秒
			for(A=1;A<=5;A+=0.04){
				for(B=0.001f;B<=0.01;B+=0.0001){
					totalError=0;
					for(int i=indexOf33;i<dataIn5Min.size();i++){
						t=(date4DataIn5Min.get(i).getTime()-TOf33)/1000;
						error=A*(1-Math.exp(-B*(t+timefacter)))+T0-dataIn5Min.get(i);
						if(i==0){
							error=0;
						}else if(i<=indexOfArea4){//给误差加上权重
							error*=W4Area4;
						}else{
							error*=W4Area6;
						}
						totalError+=error*error;
					}
					if(A==1&&B==0.001f){
						minTotalError=totalError;
						A4MinError=1;
						B4MinError=0.001f;
					}else if(totalError<minTotalError){
						minTotalError=totalError;
						A4MinError=A;
						B4MinError=B;
					}
				}
			}
			//此时A4MinError为A最佳取值
			//float Result=A4MinError+T0;
			float Result= (float) (A4MinError*(1-Math.exp(-B4MinError*(900+timefacter)))+T0-C2K);
			if((date4DataIn5Min.get(date4DataIn5Min.size()-1).getTime()-TOf33)/1000<=300){
				if(temperatureDevice.getResult4Latest3Times().size()==0){
//					temperatureDevice.setTotalResult4estimate(Result);
//					temperatureDevice.setTimes4estimate(1);
					temperatureDevice.getResult4Latest3Times().add(Result);
				}else{
					List<Float> lstReuslt=temperatureDevice.getResult4Latest3Times();
					lstReuslt.add(Result);
					float total=0;
					if(lstReuslt.size()>3){
						lstReuslt.remove(0);
					}
					for(int j=0;j<lstReuslt.size();j++){
						total+=lstReuslt.get(j);
					}
//					float total=temperatureDevice.getTotalResult4estimate()+Result;
//					temperatureDevice.setTotalResult4estimate(total);
//					int times=temperatureDevice.getTimes4estimate()+1;
//					temperatureDevice.setTimes4estimate(times);
					Result=total/lstReuslt.size();
				}
			}
			return Result;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return 0;
		}
	}
	public static float getStableValue3(List<Float> dataIn5Min,List<Date> date4DataIn5Min,Date time4Last33){
		if(date4DataIn5Min.size()<3) return 0;
		float T300=0;
		long tFirst=time4Last33.getTime();//date4DataIn5Min.get(0).getTime();
		tFirst=(time4Last33.getTime()+date4DataIn5Min.get(0).getTime())/2;
		long tLast=date4DataIn5Min.get(date4DataIn5Min.size()-1).getTime();
		long tLast2=date4DataIn5Min.get(date4DataIn5Min.size()-2).getTime();
		float Tlast=dataIn5Min.get(dataIn5Min.size()-1);
		float TLast2=dataIn5Min.get(dataIn5Min.size()-2);
		if((Tlast-tFirst)/1000>300){//五分钟的时候
			if((tLast2-tFirst)/1000==300){
				T300=TLast2;
			}else{
				T300=TLast2+(Tlast-TLast2)*(300-(tLast2-tFirst)/1000)/((tLast-tLast2)/1000);
			}
			if(T300<33.5){
				T300+=0.7;
			}else if(T300<34){
				T300+=0.7;
			}else if(T300<34.5){
				T300+=0.8;
			}else if(T300<35){
				T300+=0.9;
			}else if(T300<35.5){
				T300+=0.95;
			}else if(T300<36){
				T300+=0.9;
			}else if(T300<36.5){
				T300+=0.8;
			}else if(T300<37){
				T300+=0.8;
			}else if(T300<37.5){
				T300+=0.9;
			}else if(T300<38){
				T300+=0.9;
			}else if(T300<38.5){
				T300+=0.9;
			}else{
				T300+=0.9;
			}
		}else{//三分钟的时候
			if((tLast2-tFirst)/1000==180){
				T300=TLast2;
			}else{
				T300=TLast2+(Tlast-TLast2)*(180-(tLast2-tFirst)/1000)/((tLast-tLast2)/1000);
			}
			if(T300<33.5){
				T300+=1.3;
			}else if(T300<34){
				T300+=1.5;
			}else if(T300<34.5){
				T300+=1.7;
			}else if(T300<35){
				T300+=1.5;
			}else if(T300<35.5){
				T300+=1.3;
			}else if(T300<36){
				T300+=1.1;
			}else if(T300<36.5){
				T300+=1;
			}else if(T300<37){
				T300+=1;
			}else if(T300<37.5){
				T300+=1.1;
			}else if(T300<38){
				T300+=1.1;
			}else if(T300<38.5){
				T300+=1.1;
			}else{
				T300+=1.1;
			}
		}
		
		return T300;
	}
}
